import logging
import os
import sys
from datetime import datetime

from django.conf import settings
from django.contrib import admin, messages
from django.core import management
from django.utils.html import format_html
from django.utils.safestring import mark_safe

from lib import sina
from .forms import BackupStockForm, LiveStockForm
from .models import BackupStock, LiveStock, Dingding, LiveMonitoringPolicy

log = logging.getLogger("log")

PYTHON = "py311"
if sys.platform == "win32":
    PYTHON = "python"


class UserDataAdminMixin:
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        else:
            return qs.filter(user_id=request.user.id)

    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super().save_model(request, obj, form, change)


@admin.register(Dingding)
class DingdingAdmin(UserDataAdminMixin, admin.ModelAdmin):
    list_display = ["name", "desc"]


@admin.register(LiveMonitoringPolicy)
class LiveMonitoringPolicyAdmin(UserDataAdminMixin, admin.ModelAdmin):
    list_display = ["name", "desc", "amplitude_alert_threshold", "amplitude_alert_time_window"]


@admin.register(LiveStock)
class LiveStocksAdmin(UserDataAdminMixin, admin.ModelAdmin):
    # list_display = ["code", "name", "enable"]
    # list_editable = ["enable"]
    actions = ['restart_live', 'stop_live']
    search_fields = ["code", "name"]
    form = LiveStockForm

    def get_list_display(self, request):
        if request.user.is_superuser:
            return ["code", "name", "enable", "user"]
        else:
            return ["code", "name", "enable"]

    @admin.action(description="重启实时监控服务")
    def restart_live(self, request, queryset):
        if sys.platform == "win32":
            self.message_user(
                request,
                "Windows 系统不支持此动作",
                messages.WARNING,
            )

        cmd = f"{PYTHON} {settings.BASE_DIR.joinpath('manage.py').as_posix()} live {request.user.id}"
        awk_cmd = "awk '{print $2}'"
        kill_cmd = f"ps -ef |grep '{cmd}' |{awk_cmd} |xargs kill"
        os.system(kill_cmd)
        os.system(f"nohup {cmd} &")
        self.message_user(
            request,
            "已重启",
            messages.SUCCESS,
        )

    @admin.action(description="停止实时监控服务")
    def stop_live(self, request, queryset):
        if sys.platform == "win32":
            self.message_user(
                request,
                "Windows 系统不支持此动作",
                messages.WARNING,
            )

        cmd = f"{PYTHON} {settings.BASE_DIR.joinpath('manage.py').as_posix()} live {request.user.id}"
        awk_cmd = "awk '{print $2}'"
        kill_cmd = f"ps -ef |grep '{cmd}' |{awk_cmd} |xargs kill"
        os.system(kill_cmd)
        self.message_user(
            request,
            "已停止",
            messages.SUCCESS,
        )

    def save_model(self, request, obj, form, change):
        item = sina.get_stock_data([obj.code])[0]
        obj.name = item.name
        obj.user = request.user
        super().save_model(request, obj, form, change)


@admin.register(BackupStock)
class BackupStocksAdmin(UserDataAdminMixin, admin.ModelAdmin):
    form = BackupStockForm
    search_fields = ["code", "name"]
    list_display = ["code", "name", "ready", "current_price", "collect_datetime"]
    readonly_fields = ["user"]

    actions = ['scan']

    @admin.display(description="是否入选")
    def ready(self, instance):
        if instance.is_ready():
            return format_html(mark_safe('<span style="color:red"> 是 </span>'))
        else:
            return format_html(mark_safe('<strong> 否 </strong>'))

    @admin.action(description="重新扫描")
    def scan(self, request, queryset):
        try:
            # 调用自定义命令是阻塞执行，因此只适用于短耗时任务
            res = management.call_command("scan", request.user.pk)
            self.message_user(
                request,
                f"{res}",
                messages.SUCCESS,
            )
        except Exception as e:
            log.error(f"扫描异常：{e}", exc_info=True)
            self.message_user(
                request,
                "执行失败：" + str(e),
                messages.ERROR,
            )

    def get_action_choices(self, *args, **kwargs):
        choices = super().get_action_choices(*args, **kwargs)
        choices.pop(0)

        return sorted(choices, reverse=True)

    def save_model(self, request, obj, form, change):
        item = sina.get_stock_data([obj.code])[0]
        obj.name = item.name
        obj.current_price = item.real_price
        obj.collect_datetime = datetime.now()
        obj.user = request.user
        super().save_model(request, obj, form, change)
